home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
msgq160s.arc
/
MSGBASE.C
< prev
next >
Wrap
Text File
|
1991-10-26
|
19KB
|
756 lines
/*
* MSGBASE.C - Message handling
*
* Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
*
*/
#include <stdlib.h>
#include <io.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifdef __MSC__
#include <sys/types.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include "msged.h"
#include "p2c.h"
#include "screen.h"
#include "qmsgbase.h"
#include <assert.h>
#ifdef EIDS
#include "eidcrc.h"
#endif
#define TEXTLEN 200 /* changed when added * Origin scanning */
static BOOLEAN checkrecvd(MSG *m);
static int tputs(char *s, char **buf);
static void remap(MSG *m);
static void stripline(char *s);
static void addid(MSG *m, ADDRESS ofrom /*, char *origtext*/ );
/*
* Display activity light
*/
void working(BOOLEAN on)
{
int x,y;
static char state = 1;
x = wherex(); y = wherey();
gotoxy(maxx,1);
if (on)
bputc(state = state ^ 3);
else
bputc(' ');
gotoxy(x,y);
} /* working */
/*
* Scan the message for kludge lines and set the addressing fields
* Sets m->to and m->from
* Note: m->*.domain de-allocated if not NULL
* In msged there was something about 'thread' here which I removed
*
* Addressing information comes from the last INTL, DOMAIN or MSGID that
* was found. If none was found, looks in the Origin line for the address.
* If no origin line was found, use the address from the message header and
* a FMPT line if present.
*/
static void parsekludge(MSG *m, BUFFER *msg)
{
#ifdef EIDS
EID seid; /* EID */
#endif
MSGID msgid;
char dst[31], src[31], ddom[31], sdom[31];
int fmpt, topt;
LINE *t; /* used for scanning text */
if (m->to.domain != NULL) /* this could be dangerous */
ptrfree(m->to.domain); /* if m.to = thisnode was done */
if (m->from.domain != NULL)
ptrfree(m->from.domain);
m->from.zone = m->header.origzone;
m->from.net = m->header.orig_net;
m->from.node = m->header.orig;
m->from.point = 0;
m->from.domain = NULL;
m->to.zone = m->header.destzone;
m->to.net = m->header.dest_net;
m->to.node = m->header.dest;
m->to.point = 0;
m->to.domain = NULL;
#ifdef EIDS
memset(&(m->eid),0,sizeof(m->eid));
memset(&seid,0,sizeof(seid));
#endif
memset(&msgid,0,sizeof(msgid));
*dst = *src = EOS; /* clear all the scan variables */
fmpt = topt = 0;
memset(ddom,0,sizeof(ddom));
memset(sdom,0,sizeof(sdom));
memset(dst,0,sizeof(dst));
memset(src,0,sizeof(src));
/* now scan for kludge lines */
t = msg->first; /* first line of text */
while (t != NULL) {
msg->last = t; /* set last line */
if ((t->text != NULL) && (*(t->text) == '\01')) { /* is hidden line */
sscanf(t->text, "\01FMPT %i\n", &(fmpt));
sscanf(t->text, "\01TOPT %i\n", &(topt));
sscanf(t->text, "\01INTL %30s %30s\n", dst, src);
sscanf(t->text, "\01DOMAIN %30s %30s %30s %30s\n",ddom,dst,sdom,src);
sscanf(t->text, "\01MSGID: %30s %X\n", src, &(msgid.st));
#ifdef EIDS
sscanf(t->text, "\01EID: %x %X", &(seid.crc), &(seid.st));
#endif
} /* if */
if (strncmp(" * Origin: ",t->text,10) == 0) { /* origin line */
if (*src == EOS) { /* no source found yet */
char line2[TEXTLEN]; /* temporary origin line from msg */
char *l;
strcpy(line2,t->text);
if ((strchr(line2,'\n') == NULL) && (t->next != NULL))
strcat(line2,t->next->text); /* origin line was split */
if ((l = strrchr(line2,'(')) != NULL) {
char *m;
while (!isdigit(*l) && (*l != EOS)) l++;
m = src;
while ((*l != ')') && (m-src < 30))
*m++ = *l++;
*m = EOS; /* copy to src */
} /* if */
} /* if */
} /* if */
t = t->next; /* step on */
} /* while */
if (*src != EOS) /* INTL or DOMAIN line found */
m->from = parsenode(src);
if (*dst != EOS)
m->to = parsenode(dst);
if (fmpt && (m->from.point == 0)) /* if we already know the point */
m->from.point = fmpt; /* number don't add it */
if (topt && (m->to.point == 0))
m->to.point = topt;
#ifdef EIDS
if (seid.st != 0) /* found EID */
m->eid = seid;
#endif
if (msgid.st != 0) /* found MSGID */
m->msgid = msgid;
if (*ddom != EOS) {
m->to.domain = strdup(ddom);
assert(m->to.domain);
} /* if */
if (*sdom != EOS) {
m->from.domain = strdup(sdom);
assert(m->from.domain);
} /* if */
} /* parsekludge */
/*
* Read a message and set the addressing fields
* Text is read into global 'msgbuf'
* Return TRUE if ok
*/
BOOLEAN readmsg(MSG *m, int msgnum)
{
char *text;
clearbuffer(&msgbuf); /* clear global msg buffer */
if (!readheader(msgnum, &m->header)) /* read the header */
return FALSE;
if (arealist[area].netmail && protectnet && /* protect netmail */
(strnicmp(username, m->header.from, strlen(username)) != 0) &&
(strnicmp(username, m->header.to, strlen(username)) != 0)) {
if ((text = strdup(" * Private\r")) == NULL)
return FALSE;
} else
if ((text = readtext(&m->header)) == NULL) { /* read the text */
text = strdup(" * Read Error\r"); /* was too big or something */
if (text == NULL)
return FALSE;
}
if (*text == EOS) { /* read an empty message */
ptrfree(text);
text = strdup(" * Empty message\r");
} /* if */
msgbuf = buffer(&text);
ptrfree(text);
if (msgbuf.first == NULL)
return FALSE; /* maybe TRUE? */
parsekludge(m, &msgbuf); /* fill in addressing fields */
if (!checkrecvd(m)) return FALSE; /* set 'received' bit if neccessary */
if (msgnum > highmsgread)
highmsgread = msgnum;
return TRUE;
} /* readmsg */
/*
* Set received bit
* Return TRUE if ok
*/
static BOOLEAN checkrecvd(MSG *m)
{
int fmsg;
char *s = NULL, *t = NULL;
BOOLEAN result = FALSE;
if (m->header.bits.is_rcvd) /* already received! */
return TRUE;
if ((fmsg = filemsg(m->header.msgnum)) == -1)
return FALSE;
if ((s = strdup(username)) == NULL)
goto leave;
if ((t = (char *) calloc(1, sizeof(m->header.to)+1)) == NULL)
goto leave;
memcpy(t, m->header.to, sizeof(m->header.to)+1);
if (memicmp(s, t, strlen(s)) == 0) {
m->header.bits.is_rcvd = 1;
if (!writeheader(&m->header))
goto leave;
if (!writetoidx(fmsg,"* Received *"))
goto leave;
} /* if */
result = TRUE;
leave:
ptrfree(s);
ptrfree(t);
return(result);
} /* checkrecvd */
/*
* Do the addressing of the message before writing
*/
static void remap(MSG *m)
{
#ifdef GATE
int i;
#endif
m->header.dest_net = m->to.net;
m->header.dest = m->to.node;
m->header.destzone = m->to.zone;
/*
* we really only want to remap crash mail if a point... the boss
* node can (and probably will) handle remapping the rest
*/
if ((m->from.point) && (pointnet != 0)) { /* is a point */
if (strnicmp(m->header.to,"Areafix",7) == 0) { /* to Areafix */
m->from.net = pointnet;
m->from.node = m->from.point;
} /* if */
/* should remove this if FMPT is desired (only netmail really) */
if (!arealist[area].netmail)
m->from.point = 0; /* no .n number, i.e. now 4921/4.0 or 7102/1.0 */
} /* if */
m->header.origzone = m->from.zone;
m->header.orig_net = m->from.net;
m->header.orig = m->from.node;
/*
* don't zone gate a message if it's going somewhere in your own zone
*/
#ifdef GATE
if ((thisnode[CurAKA].zone != m->to.zone) && (!m->header.is_crash) && (arealist[area].netmail) && ((gate & GZONES) == GZONES)) {
m->header.dest_net = thisnode[CurAKA].zone;
m->header.dest = m->to.zone;
} /* if */
if (((m->to.domain != NULL) && (m->from.domain != NULL)) &&
(stricmp(m->to.domain,m->from.domain)) && ((gate & GDOMAINS) == GDOMAINS))
for (i = 0; i < domains; i++)
if (stricmp(domain_list[i].domain,m->to.domain) == 0) {
m->header.dest = domain_list[i].node;
m->header.dest_net = domain_list[i].net;
}
#endif
} /* remap */
/*
* Search through MSGTOIDX.BBS for name
* Starts at msgnum and stops at last message in board
* Returns msgnum found or -1 if error or not found
*/
int searchto(BYTE board, int msgnum, char *name)
{
int fmsg, old;
char *get;
for (;;) {
if ((fmsg = filemsg(msgnum)) == -1) return(-1);
if ((get = readtoidx(fmsg)) == NULL) return(-1);
if (strnicmp(name,get,strlen(name)) == 0)
return(msgnum);
if ((msgnum = msgnext(board,old = msgnum)) == old)
return(-1); /* last message */
} /* forever */
} /* searchto */
/*
* Mutilate bad lines without changing their length
*/
static void stripline(char *s)
{
char *p;
while ((p = strstr(s,"SEEN-BY:")) != NULL)
p[0] = '!'; /* comes out as "!EEN-BY:" */
for (p=s; *p != EOS; p++)
if (*p == '\01')
*p = '@';
} /* stripline */
/*
* Read the MSGID kludge line contents
* Return a pointer to a static buffer or NULL if nothing
*/
static char *readkludge(int num)
{
MSGHEADER header;
char *text, *msgid;
static char buf[101];
buf[0] = EOS;
if (!readheader(num, &header))
return NULL;
if (header.numrecs == 0)
return NULL;
header.numrecs = min(header.numrecs, 2); /* 2 blocks max */
if ((text = readtext(&header)) == NULL) /* read the text */
return NULL;
if ((msgid = strstr(text,"\01MSGID:")) != NULL)
if (sscanf(msgid, "\01MSGID: %100[^\r\n\215]", &buf[0]) == 1)
msgid = buf;
else
msgid = NULL;
ptrfree(text);
return msgid;
} /* readkludge */
/*
* Add the ^a kludges
*/
static void addid(MSG *m, ADDRESS ofrom /*, char *origtext*/ )
{
char buffer[TEXTLEN];
#ifdef EIDS
EID rid;
memset(&rid,0,sizeof(rid));
#endif
#ifdef PID /* JoHo's Baby */
if (arealist[area].netmail) {
sprintf(buffer, "\01PID: %s %s\n", PID, PIDVER); /* serial # opt. */
(void)insertline(&msgbuf, msgbuf.first, buffer);
}
#endif
if (msgids) {
static BYTE counter=0;
time_t t;
if (m->header.reply != 0) { /* message is a reply */
char *replyid = readkludge(m->header.reply);
if (replyid != NULL) {
sprintf(buffer,"\01REPLY: %s\n", replyid);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
} /* if */
(void)time(&t); /* could use time from message too */
t = (t<<4) | (counter++ & 15); /* for more than message/s (cc:) */
sprintf(buffer,"\01MSGID: %s %lx\n", formaddr(ofrom,Z_A|N_A|P_O|D_O),t);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
/* Add EID line here */
#ifdef EIDS
if ((eids) && (arealist[area].echomail)) {
m->eid.crc = eidcrc(origtext, m->header.from, m->header.to, m->header.subj);
m->eid.st = dostime(m->header.posttime,m->header.postdate,TRUE);
if (m->eid.st != 0) { /* EID computed ok */
if (rid.st != 0) {
sprintf(buffer, "\01EID:%04x %08lx %04x %08lx\n", m->eid.crc,
m->eid.st, rid.crc, rid.st);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} else {
sprintf(buffer, "\01EID:%04x %08lx\n", m->eid.crc, m->eid.st);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* else */
} /* if */
} /* if */
#endif
} /* addid */
/*
* Format the origin line
* The buffer must be big enough (say char[200]) to accept the origin line
*/
void formatorigin(char *buffer, char *origin, ADDRESS thisnode)
{
if (origin == NULL)
origin = username;
sprintf(buffer, " * Origin: %s (%s)\n", origin, formaddr(thisnode,Z_A|N_A|P_O|D_O));
} /* formatorigin */
/*
* Write the current message from the global text buffer
* Add origin line and remap the message
* Return TRUE if ok
*
* Steps for writing a QuickBBS message:
*
* * Search MSGIDX to see if message number already exists.
* * Modify or add receiver's name to MSGTOIDX
* * if new message: highmsg++, totalactive++, activemessages++ in MSGINFO
* * Modify or add msgnum and board to MSGIDX
* * if more text than old message, add text to end of MSGTXT, else overwrite
* * change startrec and numrec fields and write to MSGHDR
*
*/
int writemsg(MSG *m)
{
char buffer[TEXTLEN];
LINE *t;
BOOLEAN newtear = (arealist[area].echomail);
BOOLEAN neworig = newtear;
char *textbuf = NULL; /* temporary buffer for text */
BOOLEAN result = FALSE;
#ifdef EIDS
char *origtext = NULL; /* origin line text */
#endif
ADDRESS ofrom = m->from;
remap(m); /* change addressing */
/* remove the current kludge lines */
t = msgbuf.first; /* in global msgbuf */
while (t != NULL) {
if (strip && (t->text[0] == '\01')) { /* remove current hidden lines */
LINE *temp = t;
t = t->next; /* step to next line */
deleteline(&msgbuf,temp); /* and delete current line */
continue;
} /* if */
stripline(t->text); /* mutilate the rest */
if (newtear)
newtear = (strncmp(t->text,"--- ",4) != 0);
if (neworig) {
neworig = (strncmp(t->text," * Origin: ",11) != 0);
#ifdef EIDS
if (!neworig)
origtext = (t->text+11); /* old origin line */
#endif
} /* if */
t = t->next;
} /* while */
/* now add new tearline and/or origin line */
if (newtear) {
sprintf(buffer, "\n\n--- %s\n", PID " " PIDVER);
(void)insertline(&msgbuf, NULL, buffer);
}
if (neworig) { /* add origin line */
char *corigin = origin; /* default origin line */
if (!override)
if (arealist[area].areaorig != NULL) /* from ECHOORIG.CTL */
corigin = arealist[area].areaorig;
formatorigin(buffer, corigin, thisnode[CurAKA]);
t = insertline(&msgbuf, NULL, buffer);
#ifdef EIDS
origtext = (t->text+11);
#endif
} /* if */
#ifdef GATE
if ((m->from.zone != m->to.zone) && (arealist[area].netmail)) {
sprintf(buffer, "\01INTL %d:%d/%d %d:%d/%d\n",
m->to.zone, m->to.net, m->to.node,
m->from.zone, m->from.net, m->from.node);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
if (((m->to.domain != NULL) && (m->from.domain != NULL)) &&
(stricmp(m->to.domain,m->from.domain))) {
sprintf(buffer, "\01DOMAIN %s %d:%d/%d %s %d:%d/%d\n",
strupr(m->to.domain),m->to.zone, m->to.net, m->to.node,
strupr(m->from.domain),m->from.zone, m->from.net, m->from.node);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
#endif
addid(m, ofrom /*, origtext*/ ); /* add id lines */
/* Here the IFNA TOPT/FMPT kludge lines are added, in front */
#ifdef TOFMPT
if (arealist[area].netmail) {
if (m->from.point) {
sprintf(buffer,"\01FMPT %d\n", m->from.point);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
if (m->to.point) {
sprintf(buffer,"\01TOPT %d\n", m->to.point);
(void)insertline(&msgbuf, msgbuf.first, buffer);
} /* if */
} /* if */
#endif
/* write out the lines */
/* global msgbuf */
for (t = msgbuf.first; (t != NULL); t = t->next) {
char *d = buffer;
char *s = t->text;
if (s == NULL) continue;
while (*s != EOS) { /* write the message text to the buffer */
if (*s == '\n') {
*d++ = '\r';
/* *d++ = '\n'; */ /* linefeed after CR */
} else {
*d++ = *s;
} /* else */
s++;
} /* while */
if (arealist[area].softcr && (strchr(t->text,'\n') == NULL))
*d++ = 0x8d;
*d = EOS;
tputs(buffer, &textbuf); /* write the line */
} /* for */
/* add: check here if memory overflowed during message text building */
/* now write the header and text of the message */
writebase(&m->header,arealist[area].board,textbuf,
arealist[area].echomail,arealist[area].netmail);
arealist[area].new = 1;
result = TRUE;
if (textbuf != NULL)
ptrfree(textbuf);
if (curmsg(CurBoard) == 0)
setcur(CurBoard,m->header.msgnum);
#ifdef PARANOID
flushmsgbase();
#endif
return(result);
} /* writemsg */
/*
* Return current number of characters in buffer or -1 if error
*/
static int tputs(char *s, char **buf)
{
int blen, slen;
if (s == NULL)
if (*buf == NULL)
return(0);
else
return(strlen(*buf));
slen = strlen(s);
if (*buf == NULL) { /* allocate first piece of memory */
if ((*buf = malloc(slen+1)) == NULL)
return(-1); /* no memory available */
strcpy(*buf,s);
return(slen);
} /* if */
blen = strlen(*buf); /* current length */
if ((*buf = realloc(*buf, blen+slen+1)) == NULL)
return(-1); /* allocate more bytes */
strcat(*buf,s); /* add to end */
return(blen+slen); /* new length */
} /* tputs */
/*
* Look for a user in USERS.BBS
* If 'create' is TRUE, add the user
* Return user number from 0 or -1 if error or not found
*/
int searchuser(char *name, BOOLEAN create)
{
USERRECORD user;
int uf;
int count;
BOOLEAN found = FALSE;
int access = O_RDWR|O_BINARY;
if (name == NULL)
return(-1);
if (create)
access |= O_CREAT;
if ((uf = open(expandbbs("users.bbs"),access,S_IREAD|S_IWRITE)) == -1)
return(-1);
count = -1;
while (!found && (eof(uf) == 0)) {
read(uf,(char *)&user,sizeof(user));
p2c_strn(user.name,35);
found = (stricmp(user.name,name) == 0);
count++;
} /* while */
if (!found && create) {
memset(&user,0,sizeof(user));
strncpy(user.name,name,35);
c2p_str(user.name);
strcpy(user.pwd,"*no password*");
c2p_str(user.pwd);
timestr(user.lasttime,user.lastdate);
c2p_str(user.lasttime);
c2p_str(user.lastdate);
user.attrib = U_NOKILL;
if (write(uf,(char *)&user,sizeof(user)) == sizeof(user)) {
found = TRUE;
count++;
} /* if */
} /* if */
highmsgread = user.highmsgread; /* set global */
close(uf);
if (found)
return(count);
else
return(-1);
} /* searchuser */
BOOLEAN updatehigh(int usernum, int high)
{
USERRECORD user;
int uf;
if ((uf = open(expandbbs("users.bbs"),O_RDWR|O_BINARY)) == -1)
return FALSE;
if ((lseek(uf,(long)usernum*sizeof(user),SEEK_SET)) == -1) {
close(uf);
return FALSE;
} /* if */
read(uf,(char *)&user,sizeof(user));
if (high > user.highmsgread) {
user.highmsgread = high;
lseek(uf,(long)usernum*sizeof(user),SEEK_SET);
write(uf,(char *)&user,sizeof(user));
} /* if */
close(uf);
return TRUE;
} /* updatehigh */